#pragma once
#include "../core/CMath.h"
#include "../core/CUtil.h"
#if defined(__QT__)
	#include "../platform/qt/QTestCase.h"
#elif defined(__ANDROID__)
	#include "../platform/android/ATestCase.h"
#endif

class TestCase {
public:
	static void run() {
		if (Config::Released)
			return;

		static bool isRunning = false;// avoid repeated calls
		if (isRunning)
			return;
		isRunning = true;

		if (Proj::isSSQK())
			Cache::updateZhicheSpeed(30);// give a speed 30km/h to zhiche because of never-zhiche-speed value given

		#if defined(__QT__)
			QTestCase::run();
		#elif defined(__ANDROID__)
			ATestCase::run();
		#endif

		if (Config::TestCase_SampleDataEnabled) {
			s_debugModelPos = P(0, DataFilter::get()->skylineZ() * 0.95);
			CUtil::loop([] { runFixedTestCase(); }, Config::TestCase_SampleDataLoopIntervalMs);// 60Hz
		}
	}

	static void debugModelX(float x) {
		s_debugModelPos.x += x;
		LogD << "X = " << s_debugModelPos.x;
	}
	static void debugModelZ(float z) {
		s_debugModelPos.z += z;
		LogD << "Z = " << s_debugModelPos.z;
	}
	static P debugModelPos() { return s_debugModelPos; }

private:
	TestCase() = default;

	static void runFixedTestCase() {
		if (Proj::isSQ())
			runFixedTestCase_SQ();
		else if (Proj::isSSQK())
			runFixedTestCase_SSQK();
		else if (Proj::isKT())
			runFixedTestCase_KuanTi();
		else if (Proj::isSQZK())
			runFixedTestCase_SQZQ();
	}

	/******************************** KuanTi ****************************************/
	/******************************** KuanTi ****************************************/
	static void runFixedTestCase_KuanTi() {
		CVector<LineArg> lineArgs;
		lineArgs << LineArg{LineTag::L3, LineEq{{ 6, 0, 0, 0 }, 10,-100}, LineStyle::Solid, "white"};
		lineArgs << LineArg{LineTag::L2, LineEq{{ 4, 0, 0, 0 }, 10,-100}, LineStyle::Solid, "yellow"};
		lineArgs << LineArg{LineTag::L,  LineEq{{ 2, 0, 0, 0 }, 10,-100}, LineStyle::Dashed, "white"};
		lineArgs << LineArg{LineTag::R,  LineEq{{ -2, 0, 0, 0 }, 10,-100}, LineStyle::Solid, "yellow"};
		lineArgs << LineArg{LineTag::R2, LineEq{{ -4, 0, 0, 0 }, 10,-100}, LineStyle::Solid, "white"};
		lineArgs << LineArg{LineTag::R3, LineEq{{ -6, 0, 0, 0 }, 10,-100}, LineStyle::RoadEdge, "white"};
		Cache::recvLines(lineArgs);

		CVector<ModelArg> modelArgs;
		s_debugModelPos = P(0, DataFilter::get()->skylineZ() * 0.7);
		modelArgs << ModelArg{ 998877, ModelType::Car, s_debugModelPos };

		static int N = 0;
		static bool SameDir = true;
		float step = N * 0.2;
		auto truckPos = P(0, -4 - step);
		if (truckPos.z > -5)
			SameDir = true;
		else if (truckPos.z < -50)
			SameDir = false;
		if (SameDir) ++N;
		else --N;

		modelArgs << ModelArg{101, ModelType::Truck, truckPos, SameDir ? 0.0f : 3.1415926f };

		int ID = 0;
		modelArgs << ModelArg{ ++ID, ModelType::Bus, P(-4.4, -4) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(-6.4, -10) };
		modelArgs << ModelArg{ ++ID, ModelType::Truck, P(4.4, -4) };
		modelArgs << ModelArg{ ++ID, ModelType::Person, P(8.4, -5) };
		modelArgs << ModelArg{ ++ID, ModelType::Bike, P(8.4, -7) };
		modelArgs << ModelArg{ ++ID, ModelType::Moto, P(8.4, -9) };

		Cache::recvModels(modelArgs);
	}

	/******************************** SQZK ****************************************/
	/******************************** SQZK ****************************************/
	static void runFixedTestCase_SQZQ() {
		runFixedTestCase_KuanTi();
	}

	/******************************** SQ ****************************************/
	/******************************** SQ ****************************************/
	static void runFixedTestCase_SQ() {
		/***************** standalone status ***************************/
		Cache::updateSQ_NOA(sq::NOA::On);// NOA:On
		//Cache::updateSQ_ACC(sq::ACC::Follow);
		Cache::updateSQ_ALC(sq::ALC::Left);

		CVector<LineArg> lineArgs;
		lineArgs << LineArg{LineTag::L3, LineEq{{ 6.5, 0.0, 0.001, 0.0 }, 1000, -1000}, LineStyle::Solid, "white"};
		lineArgs << LineArg{LineTag::L2, LineEq{{ 4.0, 0.0, 0.001, 0.0 }, 1000, -1000}, LineStyle::Dashed, "white"};
		lineArgs << LineArg{LineTag::L, LineEq{{ 1.5, 0.0, -0.0, 0.0 }, 1000, -1000}, LineStyle::Dashed, "yellow"};
//		LineEq pointsEq;
//		pointsEq.points << P(-1,1) << P(1,0) << P(3,-3);
//		lineArgs << LineArg{LineTag::L, pointsEq, LineStyle::Solid_Dashed, "yellow"};
		lineArgs << LineArg{LineTag::R, LineEq{{ -1.5, 0.0, 0.0, 0.0 }, 1000, -1000}, LineStyle::Dashed, "white"};
		lineArgs << LineArg{LineTag::R2, LineEq{{ -4.0, 0.0, 0.0, 0.0 }, 1000, -1000}, LineStyle::Dashed, "white"};
		lineArgs << LineArg{LineTag::R3, LineEq{{ -6.5, 0.0, -0.0, 0 }, 1000, -1000}, LineStyle::RoadEdge, "white"};

		Cache::recvLines(lineArgs);

		CVector<ModelArg> modelArgs;
		modelArgs << ModelArg{ 998877, ModelType::Car, s_debugModelPos };

		static int N = 0;
		static bool SameDir = true;
		float step = N * 0.2;
		auto truckPos = P(-3, 10 - step);
		if (truckPos.z > 10)
			SameDir = true;
		else if (truckPos.z < -90)
			SameDir = false;
		if (SameDir) ++N;
		else --N;

		modelArgs << ModelArg{101, ModelType::Truck, truckPos, SameDir ? 0.0f : 3.1415926f };

		auto carPos = P(CMath::random(3.2, 3.8), CMath::random(-25, 2));
		auto personPos = P(CMath::random(-1, 1), CMath::random(-25, -2));
		modelArgs << ModelArg{102, ModelType::Car, carPos, CMath::random() * 15};
		modelArgs << ModelArg{103, ModelType::Person, personPos };

		modelArgs << ModelArg{ 100, ModelType::Barrier, P(-3.5, 7.0) };

		int ID = 1;
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(0, -37) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(-2.8, -37) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(-6, -37) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(-8.8, -37) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(-12, -37) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(-14.5, -37) };
		modelArgs << ModelArg{ ++ID, ModelType::Unknown, P(-12.8, -26.4) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(-6.8, -5.4) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(-10.4, -17.5) };
		modelArgs << ModelArg{ ++ID, ModelType::Moto, P(-6, 1.6) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(3.6, 6.6) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(8, -21.4) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(8, -3.4) };
		modelArgs << ModelArg{ ++ID, ModelType::Truck, P(8, -12.4) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(8, -33.4) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(12.8, -33.4) };
		modelArgs << ModelArg{ ++ID, ModelType::Cone, P(11.6, -12.4) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(12.8, -22.4) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(18.8, -36.4) };
		modelArgs << ModelArg{ ++ID, ModelType::Truck, P(-6.8, -22.4) };

		modelArgs << ModelArg{ ++ID, ModelType::Cone, P(-4.4, 9.5) };
		modelArgs << ModelArg{ ++ID, ModelType::Cone, P(-3.8, 9.5) };
		modelArgs << ModelArg{ ++ID, ModelType::Cone, P(-3.2, 9.5) };
		modelArgs << ModelArg{ ++ID, ModelType::Cone, P(-2.6, 9.5) };
		modelArgs << ModelArg{ ++ID, ModelType::Cone, P(-2.0, 9.5) };

		Cache::recvModels(modelArgs);
	}

	/******************************** SSQK ****************************************/
	/******************************** SSQK ****************************************/
	static void runFixedTestCase_SSQK() {
		Cache::updateSQ_NOA(sq::NOA::On);// extra status

		CVector<LineArg> lineArgs;
		lineArgs << LineArg{LineTag::L2, LineEq{{ 12, 0.0, 0.0, 0.0 }, 1000, -1000}, LineStyle::Solid, "white"};
		lineArgs << LineArg{LineTag::L, LineEq{{ 4, 0.0, 0.0, 0.0 }, 1000, -1000}, LineStyle::Dashed, "yellow"};
		lineArgs << LineArg{LineTag::R, LineEq{{ -4, 0.0, 0.0, 0.0 }, 1000, -1000}, LineStyle::Dashed, "white"};
		lineArgs << LineArg{LineTag::R2, LineEq{{ -12, 0.0, 0.0, 0.0 }, 1000, -1000}, LineStyle::Solid, "yellow"};
		Cache::recvLines(lineArgs);

		CVector<ModelArg> modelArgs;
		modelArgs << ModelArg{ 998877, ModelType::Car, s_debugModelPos };// add filed:'recog'

		static int N = 0;
		static bool SameDir = true;
		float step = N * 0.05;
		auto truckPos = P(0, -4 - step);
		if (truckPos.z > -4)
			SameDir = true;
		else if (truckPos.z < -14)
			SameDir = false;
		if (SameDir) ++N;
		else --N;
		modelArgs << ModelArg{101, ModelType::Truck, truckPos };
		modelArgs << ModelArg{ 102, ModelType::Car, P(4.4, truckPos.z) };

		int ID = 1;
		modelArgs << ModelArg{ ++ID, ModelType::Tricycle, P(-8.8, -8) };
		modelArgs << ModelArg{ ++ID, ModelType::Bus, P(-4.4, -4) };
		modelArgs << ModelArg{ ++ID, ModelType::Person, P(13.4, -5) };
		modelArgs << ModelArg{ ++ID, ModelType::Bike, P(12.4, -7) };
		modelArgs << ModelArg{ ++ID, ModelType::Moto, P(11.4, -9) };

		auto aCar = ModelArg{ ++ID, ModelType::Car, P(0, -8) };
		aCar.recog = 2;// SSQK specific status
		modelArgs << aCar;
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(-14.5, -2) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(-10.4, 0) };
		modelArgs << ModelArg{ ++ID, ModelType::Moto, P(-6, 2) };
		modelArgs << ModelArg{ ++ID, ModelType::Truck, P(8, -6) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(12.8, -2) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(12.8, 0) };
		modelArgs << ModelArg{ ++ID, ModelType::Car, P(18.8, 2) };

		Cache::recvModels(modelArgs);
	}

	static P s_debugModelPos;
};
